package com.allwees.bs.c.module.user.service.impl;

import com.allwees.bs.c.module.ops.entity.CashActiveDefEntity;
import com.allwees.bs.c.module.ops.repository.CashActiveDefRepository;
import com.allwees.bs.c.module.user.constant.ECashQueryType;
import com.allwees.bs.c.module.user.entity.UserCashEntity;
import com.allwees.bs.c.module.user.entity.UserCashLogEntity;
import com.allwees.bs.c.module.user.entity.UserEntity;
import com.allwees.bs.c.module.user.repository.UserCashLogRepository;
import com.allwees.bs.c.module.user.repository.UserCashRepository;
import com.allwees.bs.c.module.user.repository.UserRepository;
import com.allwees.bs.c.module.user.service.UserCashService;
import com.allwees.bs.core.model.coupon.constant.ECashLogType;
import com.allwees.bs.core.model.coupon.constant.ECashUseType;
import com.allwees.bs.core.modelbase.page.PageParams;
import com.allwees.bs.core.modelbase.page.PaginateDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserCashServiceImpl implements UserCashService {

    @Autowired
    private CashActiveDefRepository cashActiveDefRepository;
    @Autowired
    private UserCashRepository userCashRepository;
    @Autowired
    private UserCashLogRepository userCashLogRepository;
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserCashEntity create(String userUuid) {
        UserCashEntity userCash = userCashRepository.findByUserUuid(userUuid);
        if (userCash != null) {
            return userCash;
        }

        userCash = new UserCashEntity();
        userCash.setUserUuid(userUuid);
        userCash.setValue(BigDecimal.ZERO);
        userCashRepository.save(userCash);
        return userCash;
    }

    @Override
    @Transactional
    public UserCashEntity getCash(String userUuid) {
        return create(userUuid);
    }

    @Override
    public PaginateDTO page(String userUuid, ECashQueryType queryType, PageParams pageParams) {

        Page<UserCashLogEntity> page = null;

        if (ECashQueryType.HIS.equals(queryType)) {
            page = userCashLogRepository.findByUserUuid(userUuid, pageParams.toPageable());
        } else if (ECashQueryType.INVITE_HIS.equals(queryType)) {
            return findByInviteHis(userUuid, pageParams);
        }

        page.getContent().stream().forEach(item -> {
            if (ECashLogType.ORDER_DEDUCT.equals(item.getLogType())) {
                item.setStatus(0);
            } else {
                item.setStatus(1);
            }
        });

        PaginateDTO<UserCashLogEntity> dto = PaginateDTO.of(page.getTotalElements(), page.getContent().size(), pageParams);
        return dto.setResults(page.getContent());
    }

    private PaginateDTO findByInviteHis(String userUuid, PageParams pageParams) {
        PageImpl<UserCashLogEntity> page = userCashLogRepository.findByUserUuidAndLogType(userUuid, ECashLogType.INVITE_USER, pageParams.toPageable());

        CashActiveDefEntity cashActiveDef = cashActiveDefRepository.findByUseType(ECashUseType.SYSTEM_INVITEOR_RECEIVED);
        if (cashActiveDef == null) {
            PaginateDTO<UserCashLogEntity> dto = PaginateDTO.of(page.getTotalElements(), page.getContent().size(), pageParams);
            return dto.setResults(page.getContent());
        }

        Set<String> userUuids = page.getContent().stream().map(UserCashLogEntity::getRelateKey).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(userUuids)) {
            Map<String, UserEntity> userMap = userRepository.getByUuids(userUuids).stream().collect(Collectors.toMap(UserEntity::getUuid, o -> o));
            page.getContent().forEach(o -> o.setUser(userMap.get(o.getUuid())));
        }

        List<UserCashLogEntity> contents = new ArrayList<>(page.getContent());
        for (int i = 0; i < cashActiveDef.getSingleUserReceiveMaxCount() - page.getContent().size(); i++) {
            contents.add(new UserCashLogEntity(cashActiveDef));
        }
        PaginateDTO dto = PaginateDTO.of(contents.size(), contents.size(), pageParams);
        return dto.setResults(contents);
    }
}
